package com.blacktech.dbu.auth.controller;

import com.blacktech.dbu.auth.dto.AssignPermissionRequest;
import com.blacktech.dbu.auth.dto.PermissionResponse;
import com.blacktech.dbu.auth.dto.UpdatePermissionRequest;
import com.blacktech.dbu.auth.entity.DbuUserProduct;
import com.blacktech.dbu.auth.security.DataPermission;
import com.blacktech.dbu.auth.security.RolePermission;
import com.blacktech.dbu.auth.service.AuthorizationService;
import com.blacktech.dbu.auth.service.UserProductService;
import com.blacktech.dbu.core.dict.PermissionType;
import com.blacktech.dbu.core.dict.UserType;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户产品权限管理控制器
 *
 * @author Yanyunsong
 */
@Slf4j
@RestController
@RequestMapping("/api/auth/permissions")
@RequiredArgsConstructor
@Tag(name = "权限管理", description = "用户产品权限管理相关接口")
@RolePermission(required = UserType.Level.ADMIN)
public class PermissionController {

    private final UserProductService userProductService;
    private final AuthorizationService authorizationService;

    /**
     * 为用户分配产品权限
     */
    @PostMapping
    @Operation(summary = "分配产品权限", description = "为指定用户分配产品的访问权限")
    @DataPermission(required = PermissionType.Level.OWNER, productId = "#request.productId")
    public PermissionResponse assignPermission(@Valid @RequestBody AssignPermissionRequest request) {
        log.info("分配权限请求: userId={}, productId={}, permissionLevel={}",
                request.getUserId(), request.getProductId(), request.getPermissionLevel());

        DbuUserProduct userProduct = userProductService.assignPermission(
                request.getUserId(),
                request.getProductId(),
                request.getPermissionLevel(),
                request.getRemark()
        );

        return convertToResponse(userProduct);
    }

    /**
     * 修改用户产品权限
     */
    @PutMapping("/{userId}/{productId}")
    @Operation(summary = "修改产品权限", description = "修改用户在指定产品的权限级别")
    @DataPermission(required = PermissionType.Level.OWNER, productId = "#productId")
    public PermissionResponse updatePermission(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "产品ID") @PathVariable Long productId,
            @Valid @RequestBody UpdatePermissionRequest request) {

        log.info("修改权限请求: userId={}, productId={}, newPermissionLevel={}",
                userId, productId, request.getPermissionLevel());

        DbuUserProduct userProduct = userProductService.updatePermission(
                userId,
                productId,
                request.getPermissionLevel(),
                request.getRemark()
        );

        return convertToResponse(userProduct);
    }

    /**
     * 回收用户产品权限
     */
    @DeleteMapping("/{userId}/{productId}")
    @Operation(summary = "回收产品权限", description = "回收用户在指定产品的所有权限")
    @DataPermission(required = PermissionType.Level.OWNER, productId = "#productId")
    public void revokePermission(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "产品ID") @PathVariable Long productId) {

        log.info("回收权限请求: userId={}, productId={}", userId, productId);
        userProductService.revokePermission(userId, productId);
    }

    /**
     * 获取用户在指定产品的权限
     */
    @GetMapping("/{userId}/{productId}")
    @Operation(summary = "获取用户产品权限", description = "获取用户在指定产品的权限信息")
    @DataPermission(required = PermissionType.Level.REPORTER, productId = "#productId")
    public PermissionResponse getUserProductPermission(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "产品ID") @PathVariable Long productId) {

        log.info("获取权限请求: userId={}, productId={}", userId, productId);

        DbuUserProduct userProduct = userProductService.getUserProductPermission(userId, productId)
                .orElseThrow(() -> new RuntimeException("用户产品权限不存在"));
        return convertToResponse(userProduct);
    }

    /**
     * 获取用户所有产品权限
     */
    @GetMapping("/user/{userId}")
    @Operation(summary = "获取用户所有权限", description = "获取指定用户在所有产品的权限列表")
    public List<PermissionResponse> getUserPermissions(
            @Parameter(description = "用户ID") @PathVariable Long userId) {

        log.info("获取用户所有权限请求: userId={}", userId);

        List<DbuUserProduct> permissions = userProductService.getUserPermissions(userId);
        return permissions.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    /**
     * 获取产品的所有用户权限
     */
    @GetMapping("/product/{productId}")
    @Operation(summary = "获取产品所有权限", description = "获取指定产品的所有用户权限列表")
    @DataPermission(required = PermissionType.Level.OWNER, productId = "#productId")
    public List<PermissionResponse> getProductPermissions(
            @Parameter(description = "产品ID") @PathVariable Long productId) {

        log.info("获取产品所有权限请求: productId={}", productId);

        List<DbuUserProduct> permissions = userProductService.getProductPermissions(productId);
        return permissions.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    /**
     * 分页查询用户产品权限
     */
    @GetMapping
    @Operation(summary = "分页查询权限", description = "根据条件分页查询用户产品权限")
    @RolePermission(required = UserType.Level.SUPER_ADMIN)
    public Page<PermissionResponse> searchPermissions(
            @Parameter(description = "用户ID") @RequestParam(required = false) Long userId,
            @Parameter(description = "产品ID") @RequestParam(required = false) Long productId,
            @Parameter(description = "权限级别") @RequestParam(required = false) Integer permissionLevel,
            @Parameter(description = "页码，从0开始") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "20") int size,
            @Parameter(description = "排序字段") @RequestParam(defaultValue = "createTime") String sort,
            @Parameter(description = "排序方向") @RequestParam(defaultValue = "desc") String direction) {

        log.info("分页查询权限请求: userId={}, productId={}, permissionLevel={}, page={}, size={}",
                userId, productId, permissionLevel, page, size);

        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        Page<DbuUserProduct> permissionPage = userProductService.searchPermissions(
                userId, productId, permissionLevel, pageable);

        return permissionPage.map(this::convertToResponse);
    }

    /**
     * 获取权限统计信息
     */
    @GetMapping("/product/{productId}/stats")
    @Operation(summary = "获取权限统计", description = "获取指定产品的权限统计信息")
    @DataPermission(required = PermissionType.Level.OWNER, productId = "#productId")
    public UserProductService.PermissionStats getPermissionStats(
            @Parameter(description = "产品ID") @PathVariable Long productId) {

        log.info("获取权限统计请求: productId={}", productId);
        return userProductService.getPermissionStats(productId);
    }

    /**
     * 获取权限级别列表
     */
    @GetMapping("/levels")
    @Operation(summary = "获取权限级别", description = "获取所有可用的权限级别列表")
    public List<PermissionLevelInfo> getPermissionLevels() {
        log.info("获取权限级别列表");
        return Arrays.stream(PermissionType.values())
                .map(t -> new PermissionLevelInfo(t.getPermissionLevel(), t.name(), t.getDisplayName(), t.getDescription()))
                .toList();
    }

    /**
     * 转换为响应DTO
     */
    private PermissionResponse convertToResponse(DbuUserProduct userProduct) {
        PermissionResponse response = new PermissionResponse();
        response.setId(userProduct.getId());
        response.setUserId(userProduct.getUser().getId());
        response.setUsername(userProduct.getUser().getUsername());
        response.setUserDisplayName(userProduct.getUser().getDisplayName());
        response.setProductId(userProduct.getProduct().getId());
        response.setProductCode(userProduct.getProduct().getProductCode());
        response.setProductName(userProduct.getProduct().getProductName());

        // 设置权限级别
        response.setPermissionLevel(userProduct.getPermissionLevel());

        // 根据权限级别设置显示名称和描述
        String[] permissionInfo = getPermissionInfoByLevel(userProduct.getPermissionLevel());
        response.setPermissionLevelDisplayName(permissionInfo[0]);
        response.setPermissionLevelDescription(permissionInfo[1]);

        response.setRemark(userProduct.getRemark());
        response.setCreateTime(userProduct.getCreateTime());
        response.setUpdateTime(userProduct.getUpdateTime());

        if (userProduct.getAssignedBy() != null) {
            response.setAssignedById(userProduct.getAssignedBy().getId());
            response.setAssignedByUsername(userProduct.getAssignedBy().getUsername());
            response.setAssignedByDisplayName(userProduct.getAssignedBy().getDisplayName());
        }

        return response;
    }

    /**
     * 根据权限级别获取对应的显示信息
     *
     * @return [displayName, description]
     */
    private String[] getPermissionInfoByLevel(Integer permissionLevel) {
        if (permissionLevel == null) {
            return new String[]{"未知", "未知权限级别"};
        }
        return switch (permissionLevel) {
            case 1 -> new String[]{"产品负责人", "完全控制权限"};
            case 2 -> new String[]{"产品协作员", "读写权限"};
            case 3 -> new String[]{"产品报告员", "只读权限"};
            default -> new String[]{"未知", "未知权限级别"};
        };
    }

    /**
     * 权限级别信息
     */
    public record PermissionLevelInfo(int level, String code, String displayName, String description) {
    }
}